package com.lagou.cl.core;

import com.lagou.cl.pojo.MappedContext;
import com.lagou.cl.pojo.MappedHost;
import com.lagou.cl.pojo.MappedWrapper;
import com.lagou.cl.pojo.Mapper;
import com.lagou.cl.server.ConnectorProcessor;
import com.lagou.cl.util.MyClassLoader;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.ArrayList;
import java.util.List;


public class StandardHost implements Lifecycle {

	/**
	 * 虚拟主机的名称：localhost
	 */
	private String name;

	/**
	 * webapps 路径
	 */
	private String appBase;

	private List<StandardContext> standardContexts;


	@Override
	public void init() {

	}

	@Override
	public void start() {

		List<MappedContext> mappedContexts = new ArrayList<>();
		for (StandardContext context : this.standardContexts) {
			try {
				//加载appBase下的项目
				List<MappedContext> mappedContext = loadContext(context, appBase);
				mappedContexts.addAll(mappedContext);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		//封装Mapper
		for (Connector connector : Mapper.mappedConnector) {
			Integer port = connector.getPort();

			MappedHost mappedHost = new MappedHost(name + ":" + port, port);
			mappedHost.getMappedContexts().addAll(mappedContexts);
			Mapper.mappedHosts.add(mappedHost);
		}

		//开启监听
		for (Connector connector : Mapper.mappedConnector) {
			ConnectorProcessor connectorProcessor = new ConnectorProcessor(connector.getPort());
			connectorProcessor.start();
			//TheadPoolUtil.getThreadPoolExecutor().execute(connectorProcessor);
		}
	}

	private List<MappedContext> loadContext(StandardContext context, String appBasePath) throws Exception {
		String docBase = context.getDocBase();
		//该项目的上下文路径
		String contextPath = context.getPath();

		String modulePath = appBasePath + "/" + docBase;
		modulePath = modulePath.replaceAll("\\\\", "/");
		String webXmlPath = modulePath + "/web.xml";
		//System.out.println("modulePath: " + modulePath + "\nwebXmlPath: " + webXmlPath);

		List<MappedContext> mappedContextList = new ArrayList<>();
		File file = new File(webXmlPath);
		if (file.exists()) {
			System.out.println("module:" + docBase);
			//构造项目
			MappedContext mappedContext = new MappedContext(contextPath, modulePath);
			//读取web.xml中配置的servlet
			mappedContext.setExactWrappers(loadWebConfig(contextPath, modulePath, webXmlPath));
			mappedContextList.add(mappedContext);
		}
		return mappedContextList;
	}

	private List<MappedWrapper> loadWebConfig(String contextPath, String modulePath, String webXmlPath) throws Exception {
		List<MappedWrapper> mappedWrapperList = new ArrayList<>();
		// region 1.使用dom4j解析核心配置文件
		Document document = new SAXReader().read(new File(webXmlPath));
		Element rootElement = document.getRootElement();
		//查找所有的property节点
		List<Element> list = rootElement.elements("servlet");
		//rootElement.selectNodes
		for (Element servlet : list) {

			Element servletNameElement = servlet.element("servlet-name");
			String servletName = servletNameElement.getTextTrim();
			Element servletClassElement = servlet.element("servlet-class");
			String servletClass = servletClassElement.getStringValue();

			new MyClassLoader(modulePath + "/classes/" + "Servlet.class").loadClass("com.lagou.cl.servlet.Servlet");
			new MyClassLoader(modulePath + "/classes/" + "AbstractHttpServlet.class").loadClass("com.lagou.cl.servlet.AbstractHttpServlet");


			List<Element> servletMappings = rootElement.elements("servlet-mapping");
			for (Element servletMapping : servletMappings) {
				Element servletMappingNameElement = servletMapping.element("servlet-name");
				String servletMappingName = servletMappingNameElement.getTextTrim();
				if (servletMappingName.equals(servletName)) {
					Element urlPattern = servletMapping.element("url-pattern");
					String classFilePath = modulePath + "/classes/" + servletClass.replace(".", "/") + ".class";
					//System.out.println("加载servlet: " + classFilePath);

					MyClassLoader myClassLoader = new MyClassLoader(classFilePath);
					Class<?> aClass = myClassLoader.loadClass(servletClass);
					//System.out.println("servlet: " + aClass + "\n");
					MappedWrapper mappedWrapper = new MappedWrapper(contextPath + urlPattern.getStringValue(), aClass.newInstance());
					mappedWrapperList.add(mappedWrapper);
				}
			}
		}
		return mappedWrapperList;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAppBase() {
		return appBase;
	}

	public void setAppBase(String appBase) {
		this.appBase = appBase;
	}

	public List<StandardContext> getStandardContexts() {
		return standardContexts;
	}

	public void setStandardContexts(List<StandardContext> standardContexts) {
		this.standardContexts = standardContexts;
	}

}
